package com.logic.landseaserver.service.impl;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.Format;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.logic.common.domain.Code;
import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.QueryUtil;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.exception.LandseaBusinessException;
import com.logic.landseaserver.common.util.LandSeaUtil;
import com.logic.landseaserver.domain.Room;
import com.logic.landseaserver.domain.RoomType;
import com.logic.landseaserver.domain.SystemCode;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.RoomReadMapper;
import com.logic.landseaserver.persistence.write.RoomWriteMapper;
import com.logic.landseaserver.persistence.write.UrgentWriteMapper;
import com.logic.landseaserver.service.IProjectAppartment;
import com.logic.landseaserver.service.IProjectService;
import com.logic.landseaserver.ws.dto.ProjectDetailDTO;
import com.logic.landseaserver.ws.dto.RoomDTO;
import com.logic.landseaserver.ws.dto.RoomDetailDTO;
import com.logic.landseaserver.ws.dto.RoomTypeDTO;
import com.logic.landseaserver.ws.request.ContractNeedDelReq;
import com.logic.landseaserver.ws.request.RoomDetailReq;
import com.logic.landseaserver.ws.request.RoomStatusListReq;
import com.logic.landseaserver.ws.request.RoomStatusStatisticReq;
import com.logic.landseaserver.ws.response.RoomStatisticListResp;
import com.logic.system.service.ICodeService;
import com.logic.system.service.IConfigurationService;


@Service
public class ProjectAppartmentImpl implements IProjectAppartment {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RoomReadMapper roomReadMapper;
    @Autowired
    private ICodeService codeService;

    @Autowired
    private RoomWriteMapper roomWriteMapper;

    @Autowired
    HttpServletRequest request;
    @Autowired
    private IProjectService projectServiceImpl;
    @Autowired
    private ContractReadMapper contractReadMapper;
    @Autowired
    private UrgentWriteMapper urgentWriteMapper;
    @Autowired
    IConfigurationService configurationService;

    @Override
    public List<Object> queryByPage(QueryUtil queryUtil, Integer projectId) {
        queryUtil.getParams().put("userId", SecurityUtils.getCurrentLogin().getUserId());
        queryUtil.getParams().put("projectId", projectId);
        List<Object> dtoList = roomReadMapper.selectByPage(queryUtil);
        return dtoList;
    }

    @Override
    public void delete(String ids) throws BusinessException {

        String[] idArr = ids.split(",");
        for (String id : idArr) {
            Room room = new Room();
            room.setId(Integer.parseInt(id));
            room.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            roomWriteMapper.deleteByPrimaryKey(room);
        }
    }

    @Override
    public void updateStatus(Room room) throws BusinessException {
        room.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        roomWriteMapper.updateStatus(room);
    }

    @Override
    public void updateAppendStatus(Room room) throws BusinessException {
        room.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        roomWriteMapper.updateAppendStatus(room);
    }

    @Override
    public Object get(Integer arg0) throws BusinessException {
        return null;
    }

    @Override
    public int insertRoomDetail(RoomDetailDTO obj) throws SecurityException, BusinessException {
        int projectAppartmentInt = -1;
        if (validateForInsert(obj)) {
            Room room = new Room();
            room = (Room) fieldToObject(obj, room);
            room.setRoomStyle(obj.getDecorateStyle());
            room.setRoomDivice(obj.getDevices());
            room.setRoomDirection(obj.getDirection());
            room.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            //room.setAppendStatus("");
            //设置编码
            int projectId = obj.getPrjId();
            Integer maxnum = roomReadMapper.getMaxRoomCode(projectId);
            if (maxnum == null) {
                maxnum = 1;
            } else {
                maxnum = maxnum + 1;
            }

            Format f1 = new DecimalFormat("0000");
            String roomcode = obj.getPrjCode() + f1.format(maxnum).toString();
            room.setRoomCode(roomcode);
            roomWriteMapper.insertSelective(room);
            projectAppartmentInt = room.getId();

//			//插入设施
//			RoomDetailDTO roomReq = (RoomDetailDTO)obj;
//			List<CodeReference> param = new ArrayList<CodeReference>();
//			String device = roomReq.getDevices();
//			String[] devicelist = device.split(",");
//			for(String dev :devicelist){
//				CodeReference code = new CodeReference();
//				code.setType("LT2");
//				code.setObjectId(projectAppartmentInt);
//				code.setSystemCode(dev);
//				code.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
//				param.add(code);
//			}
//			roomWriteMapper.insertRoomCode(param);
        }
        return projectAppartmentInt;
    }

    @Override
    public int editRoomDetail(Object obj) throws SecurityException, BusinessException {
        RoomDetailDTO roomReq = (RoomDetailDTO) obj;
        Room orgRoom = roomReadMapper.selectByPrimaryKey(roomReq.getId());
        if(orgRoom==null){
            throw new LandseaBusinessException(LandseaErrorMessageEnum.UPDATE_ROOM_NULL);
        }
        int projectAppartmentInt = -1;
        if (validateForInsert(obj)) {
          //  RoomDetailDTO roomReq = (RoomDetailDTO) obj;
            Room room = new Room();
            room = (Room) fieldToObject(obj, room);
            room.setRoomStyle(roomReq.getDecorateStyle());
            room.setRoomDivice(roomReq.getDevices());
            room.setRoomDirection(roomReq.getDirection());
            projectAppartmentInt = room.getId();
            room.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            //更新room
            roomWriteMapper.updateByPrimaryKeySelective(room);
            logger.info("update room id is [originalInfo] :"+orgRoom.getId() +" rent price is :"+ orgRoom.getRent()+"  originalPrice is: "+orgRoom.getOriginalPrice());
            logger.info("update room id is [newInfo] :"+roomReq.getId() +" rent price is :"+ roomReq.getRent()+"  originalPrice is: "+roomReq.getOriginalPrice());
        }
        return projectAppartmentInt;
    }


    public RoomDetailReq searchRoomInfo(int id) {
        Room resultlist = roomReadMapper.selectRoomInfo(id);
        RoomDetailReq roominfo = new RoomDetailReq();
        roominfo = (RoomDetailReq) fieldToObject(resultlist, roominfo);
        roominfo.setDecorateStyle(resultlist.getRoomStyle());
        roominfo.setDevices(resultlist.getRoomDivice());
        roominfo.setDirection(resultlist.getRoomDirection());
        //获取项目相关信息
        ProjectDetailDTO pdd = projectServiceImpl.getProjectDetail(roominfo.getPrjId());
        roominfo.setProject(pdd);
        return roominfo;
    }

    //obj1 赋值给obj2
    public Object fieldToObject(Object obj, Object getobj) {
        Field[] field = obj.getClass().getDeclaredFields();
        Field[] rField = getobj.getClass().getDeclaredFields();
        List<String> rName = new ArrayList<String>();
        for (Field f : rField) {
            rName.add(f.getName());
        }
        Class rclazz = getobj.getClass();
        for (int j = 0; j < field.length; j++) {
            // 获取属性的名字
            String name = field[j].getName();
            String type = field[j].getGenericType().toString();

            if (rName.contains(name)) {   //赋值给room对象
                String nameUpper = name.substring(0, 1).toUpperCase() + name.substring(1);
                try {
                    if (type.equals("class java.lang.String")) {
                        Method m = obj.getClass().getMethod("get" + nameUpper);
                        String value = (String) m.invoke(obj);
                        PropertyDescriptor pd = null;
                        try {
                            pd = new PropertyDescriptor(name, rclazz);
                        } catch (IntrospectionException e) {
                            logger.error("fieldToObject error.", e);
                        }
                        Method setMethod = pd.getWriteMethod();
                        if (value != null && !"".equals(value)) {
                            setMethod.invoke(getobj, value);
                        }
                    }
                    if (type.equals("class java.lang.Integer")) {
                        Method m = obj.getClass().getMethod("get" + nameUpper);
                        Integer value = (Integer) m.invoke(obj);
                        PropertyDescriptor pd = null;
                        try {
                            pd = new PropertyDescriptor(name, rclazz);
                        } catch (IntrospectionException e) {
                            logger.error("fieldToObject error.", e);
                        }
                        Method setMethod = pd.getWriteMethod();
                        if (value != null && !"".equals(value)) {
                            setMethod.invoke(getobj, value);
                        }
                    }
                    if (type.equals("class java.lang.Long")) {
                        Method m = obj.getClass().getMethod("get" + nameUpper);
                        Long value = (Long) m.invoke(obj);
                        PropertyDescriptor pd = null;
                        try {
                            pd = new PropertyDescriptor(name, rclazz);
                        } catch (IntrospectionException e) {
                            logger.error("fieldToObject error.", e);
                        }
                        Method setMethod = pd.getWriteMethod();
                        if (value != null && !"".equals(value)) {
                            setMethod.invoke(getobj, value);
                        }
                    }
                    if (type.equals("class java.lang.Double")) {
                        Method m = obj.getClass().getMethod("get" + nameUpper);
                        Double value = (Double) m.invoke(obj);
                        PropertyDescriptor pd = null;
                        try {
                            pd = new PropertyDescriptor(name, rclazz);
                        } catch (IntrospectionException e) {
                            logger.error("fieldToObject error.", e);
                        }
                        Method setMethod = pd.getWriteMethod();
                        if (value != null && !"".equals(value)) {
                            setMethod.invoke(getobj, value);
                        }
                    }
                    if (type.equals("class java.lang.Float")) {
                        Method m = obj.getClass().getMethod("get" + nameUpper);
                        Float value = (Float) m.invoke(obj);
                        PropertyDescriptor pd = null;
                        try {
                            pd = new PropertyDescriptor(name, rclazz);
                        } catch (IntrospectionException e) {
                            logger.error("fieldToObject error.", e);
                        }
                        Method setMethod = pd.getWriteMethod();
                        if (value != null && !"".equals(value)) {
                            setMethod.invoke(getobj, value);
                        }
                    }
                    if (type.equals("class java.util.Date")) {
                        Method m = obj.getClass().getMethod("get" + nameUpper);
                        Date value = (Date) m.invoke(obj);
                        PropertyDescriptor pd = null;
                        try {
                            pd = new PropertyDescriptor(name, rclazz);
                        } catch (IntrospectionException e) {
                            logger.error("fieldToObject error.", e);
                        }
                        Method setMethod = pd.getWriteMethod();
                        if (value != null && !"".equals(value)) {
                            setMethod.invoke(getobj, value);
                        }
                    }
                } catch (NoSuchMethodException e) {
                    logger.error("fieldToObject error.", e);
                } catch (SecurityException e) {
                    logger.error("fieldToObject error.", e);
                } catch (IllegalAccessException e) {
                    logger.error("fieldToObject error.", e);
                } catch (IllegalArgumentException e) {
                    logger.error("fieldToObject error.", e);
                } catch (InvocationTargetException e) {
                    logger.error("fieldToObject error.", e);
                }
            }
        }
        return getobj;
    }


    @Override
    public List<?> query(QueryUtil arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void update(Object arg0) throws LandseaBusinessException {
        Room room = (Room) arg0;
        if (room == null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.UPDATE_ROOM_NULL);
        }
        if (room.getId() == null) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.UPDATE_ROOM_NULL);
        }

        room.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        roomWriteMapper.updateByPrimaryKeySelective(room);

    }

    @Override
    public Boolean validate(Object arg0) throws BusinessException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Boolean validateForDelete(Object arg0) throws BusinessException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Boolean validateForInsert(Object obj) throws BusinessException {

        return Boolean.valueOf(true);
    }

    @Override
    public Boolean validateForUpdate(Object arg0) throws BusinessException {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int insert(Object arg0) throws BusinessException {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public List<SystemCode> searchRoomStatusList() {
        // TODO Auto-generated method stub
        List<SystemCode> statuslist = roomReadMapper.searchRoomStatusList();
        return statuslist;
    }

    @Override
    public List<SystemCode> searchRoomAppendStatusList() {
        // TODO Auto-generated method stub
        List<SystemCode> statuslist = roomReadMapper.searchRoomAppendStatusList();
        return statuslist;
    }

    @Override
    public List<SystemCode> searchRoomTypeByProjectID(int id) {
        // TODO Auto-generated method stub
        List<SystemCode> typelist = roomReadMapper.roomTypeByProjectID(id);
        return typelist;
    }

    @Override
    public List<SystemCode> searchRoomTypeList() {
        // TODO Auto-generated method stub
        List<SystemCode> typelist = roomReadMapper.searchRoomTypeList();
        return typelist;
    }

    @Override
    public List<SystemCode> searchDecorateStyleByProjectID(int id) {
        List<SystemCode> result = roomReadMapper.searchDecorateStyleByProjectID(id);
        return result;
    }

    @Override
    public RoomType getDecoratePic(Integer id) {
        RoomType picresult = roomReadMapper.getDecoratePic(id);
        return picresult;
    }

    @Override
    public void deletePrjStylePic(RoomType roomType) {
        roomWriteMapper.deletePrjStylePic(roomType);
    }

    @Override
    public Integer savePrjPicAndInfo(RoomType roomType) {
        int returnid = -1;
        int prjid = roomType.getPrjId();
        String roomtype = roomType.getTypeCode();
        Integer exist = roomReadMapper.ChackRoomTypeExist(roomType);
        roomType.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        if (0 == exist) {
            roomWriteMapper.insertPicAndInfo(roomType);
            returnid = roomType.getId();
        } else {
            roomWriteMapper.updatePicAndInfo(roomType);
            returnid = roomType.getId();
        }
        return returnid;
    }

    /**
     * [描述]：事务已添加</br>
     *
     * @throws BusinessException
     */
    @Override
    @Transactional(rollbackFor = {BusinessException.class, Exception.class})
    public void test() throws BusinessException {

        for (int i = 1; i <= 3; i++) {
            urgentWriteMapper.deleteUrgent(i);
            if (i == 2) {
                throw new BusinessException("3243");
            }
        }
    }

    @Override
    public void resetNoPayRoom(List<ContractNeedDelReq> list) {
        if (list != null && list.size() > 0) {
            roomWriteMapper.resetNoPayRoom(list);
        }
    }

    @Override
    public RoomDTO getAppendInfo(Integer id) throws LandseaBusinessException {


        return roomReadMapper.getAppendInfo(id);

    }

    @Override
    public List<RoomTypeDTO> queryRoomTypeList(QueryUtil queryUtil, Integer projectId) {

        queryUtil.getParams().put("userId", SecurityUtils.getCurrentLogin().getUserId());
        queryUtil.getParams().put("projectId", projectId);
        List<RoomTypeDTO> result = roomReadMapper.getRoomTypeList(queryUtil);
        return result;
    }

    @Override
    public List<RoomTypeDTO> queryAllRoomTypeList(QueryUtil queryUtil) {
        List<RoomTypeDTO> result = roomReadMapper.getRoomTypeList(queryUtil);
        return result;
    }

    @Override
    public void deleteRoomType(String ids) {
        List<String> idlist = Arrays.asList(ids.split(","));
        Integer a = roomWriteMapper.deleteRoomType(idlist);
    }

    @Override
    public List<SystemCode> getValideDecorateStyle(int id) {
        List<SystemCode> result = roomReadMapper.searchValidateDecorateStyle(id);
        return result;
    }

    @Override
    public List queryRoomList(RoomStatusListReq req) {

        Integer moveDays = configurationService.getIntegerValue("CONTRACT_MOVE_DAYS");
        req.setMoveDays(moveDays == null ? 7 : moveDays);
        List<RoomDTO> list = roomReadMapper.selectRoomPage(req);
        Map<String, List<RoomDTO>> map = new TreeMap<String, List<RoomDTO>>();
        if (list != null && list.size() > 0) {
            for (RoomDTO resp : list) {
                String newKey = addZeroForNum(resp.getBuildNum(), 8);
                if (map.containsKey(newKey)) {
                    List<RoomDTO> list1 = map.get(newKey);
                    list1.add(resp);
                } else {
                    List<RoomDTO> list1 = new ArrayList<RoomDTO>();
                    list1.add(resp);
                    map.put(newKey, list1);
                }
            }
        }

        List resultList = new ArrayList<List<RoomDTO>>(map.values());
        return resultList;
    }

    public String addZeroForNum(String str, int strLength) {
        int strLen = str.length();
        if (strLen < strLength) {
            while (strLen < strLength) {
                StringBuffer sb = new StringBuffer();
                sb.append("0").append(str);// 左补0
                // sb.append(str).append("0");//右补0
                str = sb.toString();
                strLen = str.length();
            }
        }
        return str;
    }

    @Override
    public Map<String, Object> roomStatistic(RoomStatusStatisticReq req) throws LandseaBusinessException {

        Integer adminId = SecurityUtils.getCurrentLogin().getUserId();
        if (adminId == null || adminId == -1) {
            throw new LandseaBusinessException(LandseaErrorMessageEnum.TOKEN_IS_NULL);
        }
        req.setAdminId(adminId);
        List<RoomStatisticListResp> list = roomReadMapper.roomStatistic(req);
        Map<String, RoomStatisticListResp> map = new HashMap<String, RoomStatisticListResp>();
        if (list.size() > 0) {
            for (RoomStatisticListResp resp : list) {
                map.put(resp.getAppendStatus(), resp);
            }
        }

        List<Code> childCodeList = codeService.getChildCodes("_LRB");
        for (Code code : childCodeList) {
            if (!map.containsKey(code.getCode())) {
                RoomStatisticListResp resp = new RoomStatisticListResp();
                resp.setAppendStatus(code.getCode());
                resp.setAppendStatusZh(code.getCodeDescZh());
                resp.setCount(0);
                map.put(code.getCode(), resp);
            }
        }
        List resultList = new ArrayList<RoomStatisticListResp>(map.values());
        Collections.sort(resultList, new Comparator<RoomStatisticListResp>() {
            public int compare(RoomStatisticListResp o1, RoomStatisticListResp o2) {
                return o1.getAppendStatus().compareTo(o2.getAppendStatus());
            }
        });
        Map<String, Object> result = new HashMap<>();
        result.put("statistic", resultList);
        //预离统计
        Integer moveDays = configurationService.getIntegerValue("CONTRACT_MOVE_DAYS");
        req.setMoveDays(moveDays == null ? 7 : moveDays);
        Integer moveCnt = contractReadMapper.queryContractByMoving(req);
        result.put("moveTip", moveCnt == null ? 0 : moveCnt);
        //脏房统计
        result.put("dirty", roomReadMapper.roomDirtyStatistic(req));
        //滞纳金统计
        result.put("arrears", roomReadMapper.roomArrearsStatistic(req));
        result.put("offrent", roomReadMapper.roomOffRentStatistic(req));
        //签约未入住
        result.put("nosignin", roomReadMapper.roomNosigninStatistic(req));
        //门锁异常数量
        result.put("lockWarning", roomReadMapper.roomlockWarning(req));
        //统计distinct预定签约未入住
        result.put("disctSignAndDeposit", roomReadMapper.roomDistSignAndDeposit(req));

        // 系统均价
        Double systemFloorPrice = roomReadMapper.roomSystemFloorPrice(req);
        if (null == systemFloorPrice)
        {
            systemFloorPrice = new Double(0.00d);
        }
        //系统均价
        result.put("systemFloorPrice", LandSeaUtil.get2Double(systemFloorPrice));
    
        // 系统均价
        Double realFloorPrice = roomReadMapper.roomRealFloorPrice(req);
        if (null == realFloorPrice)
        {
            realFloorPrice = new Double(0.00d);
        }        
        //实际均价
        result.put("realSalePrice", LandSeaUtil.get2Double(realFloorPrice));
        
        return result;
    }

}
